package com.epam.task.xml.parsers;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;

import java.util.*;

public class ListSAXExample extends DefaultHandler {
    public static final Logger LOGGER = LoggerFactory.getLogger(SAXAnalyzer.class);
    HashMap nameToFactory;
    HashMap nameToAnalogs;
    HashMap nameToVersion;
    HashMap nameToCertificate;
    StringBuffer accumulator;
    String medicineName, medicineFactory, medicineAnalogs;
    String medicineId;
    String medicineGroup;
    String medicineNameVersion;
    String medicineCertificate;
    String medicinePackage;
    String medicineDosage;
    String registrationCode, deadLine, organization;
    String kind, count, price;
    String dose, measure, frequency;

    public void startDocument() {
        accumulator = new StringBuffer();
        nameToFactory = new HashMap();
        nameToAnalogs = new HashMap();
        nameToVersion = new HashMap();
        nameToCertificate = new HashMap();
        System.out.println("Parsing started..");
    }

    public void characters(char[] buffer, int start, int length) {
        accumulator.append(buffer, start, length);
    }

    public void startElement(String namespaceURL, String localName,
                             String qName, Attributes attributes) {
        accumulator.setLength(0);
        if (qName.equals("medicine")) {
            medicineId = attributes.getValue("uid");
            medicineGroup = attributes.getValue("group");
        }
    }

    public void endElement(String namespaceURL, String localName, String qname) {
        if (localName.equals("name")) { // Store servlet name
            medicineName = accumulator.toString().trim();
        } else if (localName.equals("factory")) { // Store servlet class
            medicineFactory = accumulator.toString().trim();
        } else if (localName.equals("nameAnalog")) { // Store servlet pattern
            medicineAnalogs = accumulator.toString().trim();
        } else if (localName.equals("nameVersion")) { // Store servlet pattern
            medicineNameVersion = accumulator.toString().trim();
        } else if (localName.equals("registrationCode")) { // Store servlet pattern
            registrationCode = accumulator.toString().trim();
        } else if (localName.equals("deadline")) { // Store servlet pattern
            deadLine = accumulator.toString().trim();
        } else if (localName.equals("organization")) { // Store servlet pattern
            organization = accumulator.toString().trim();
        } else if (localName.equals("kind")) { // Store servlet pattern
            kind = accumulator.toString().trim();
        } else if (localName.equals("count")) { // Store servlet pattern
            count = accumulator.toString().trim();
        } else if (localName.equals("price")) { // Store servlet pattern
            price = accumulator.toString().trim();
        } else if (localName.equals("dose")) { // Store servlet pattern
            dose = accumulator.toString().trim();
        } else if (localName.equals("measure")) { // Store servlet pattern
            measure = accumulator.toString().trim();
        } else if (localName.equals("frequency")) { // Store servlet pattern
            frequency = accumulator.toString().trim();
        } else if (localName.equals("medicine")) { // Map name to class
            nameToFactory.put(medicineName, medicineFactory);
        } else if (localName.equals("analogs")) {// Map name to pattern
            List patterns = (List) nameToAnalogs.get(medicineName);
            if (patterns == null) {
                patterns = new ArrayList();
                nameToAnalogs.put(medicineName, patterns);
            }
            patterns.add(medicineAnalogs);
        } else if (localName.equals("certificate")) {// Map name to pattern
            List patterns = (List) nameToCertificate.get(medicineNameVersion);
            if (patterns == null) {
                patterns = new ArrayList();
                nameToCertificate.put(medicineNameVersion, patterns);
            }
            patterns.add(medicineCertificate);
        }
    }

    public void endDocument() {
        List medicineNames = new ArrayList(nameToFactory.keySet());
        Collections.sort(medicineNames);
        for (Iterator iterator = medicineNames.iterator(); iterator.hasNext(); ) {
            String name = (String) iterator.next();
            String classname = (String) nameToFactory.get(name);
            List patterns = (List) nameToAnalogs.get(name);
            System.out.println("Medicine of group '" + medicineGroup + "' "
                    + ((medicineId != null) ? " (uid=" + medicineId + ")" : "") + ": " + name);
            System.out.println("Factory: " + classname);
            if (patterns != null) {
                System.out.println("Analogs:");
                for (Iterator i = patterns.iterator(); i.hasNext(); ) {
                    System.out.println("\t" + i.next());
                }
            }
            List medicineNamesVersion = new ArrayList(nameToCertificate.keySet());
            Collections.sort(medicineNamesVersion);
            for (Iterator iterator1 = medicineNamesVersion.iterator(); iterator1.hasNext(); ) {
                String nameVersion = (String) iterator1.next();
                List certificate = (List) nameToCertificate.get(nameVersion);
                System.out.println("Release: " + nameVersion);
                if (certificate != null) {
                    System.out.println("Certificate: #" + registrationCode
                            + " from " + deadLine + " of " + organization);
                    System.out.println("Package: " + kind
                            + " available " + count + " pcs." + " cost " + price);
                    System.out.println("Dosage: " + dose
                            +  measure + " with periodicity " + frequency);
                }

            }

        }
        System.out.println("Parsing end.");
    }

    public void warning(SAXParseException exception) {
        System.err.println("WARNING: line " + exception.getLineNumber() + ": "
                + exception.getMessage());
    }

    public void error(SAXParseException exception) {
        System.err.println("ERROR: line " + exception.getLineNumber() + ": "
                + exception.getMessage());
    }

    public void fatalError(SAXParseException exception) throws SAXException {
        System.err.println("FATAL: line " + exception.getLineNumber() + ": "
                + exception.getMessage());
        throw (exception);
    }
}
